Hello, OS world
编译, 链接
- strace -f查看进程和他的子进程的所有系统调用
- gcc -o hello hello.c
- 子进程1: 编译器compiler写入a.s汇编代码
- 子进程2: 汇编器assembler写入a.o(ELF…)
- 子进程3: 链接器linker写入a.out(ELF…)
- readelf: hello中有什么
终端与shell
- I/O设备模型: 设备是三种操作的集合:
- 发送命令、读取状态、传输数据
- 设备驱动: os中负责与设备交互的程序. 根据设备类型不同, 给每一类设备以统一的接口访问, 实现这个接口的就是设备驱动程序.
- shell用read从0号文件描述符读入, 按下回车read返回
./hello如何被执行
- fork-execve
- execve保留绝大部分进程状态,如文件描述符, 管道和重定向是改变文件描述符
- sudo echo hello > /etc/a没用的原因: 在execve之前open就已经失败了,还没有sudo
hello的第一条指令在哪里?
- ld.so的_start()
hello的main函数执行之前, 系统中发生了什么?
- 加载器的$_$start, $_$init, 之后调用hello的 $_$start, $__$libc$_$start$_$main…
- gdb: starti
- 发现在加载器的$_$start()(这是动态链接, 对于静态链接就是在程序里)
- info inferiors + pmap
- 有hello, ld-xxx.so
- 没有看到libc代码
- b $_$start() + 再次pmap
- 有了libc(加载器做的mmap)
- 最后到main()
- constructor函数: 可以在main之前执行
- printf可能会被优化为puts
printf()代码位置
- 动态链接细节不考, 如got plt
printf()是线程安全的吗?如何实现线程安全的printf?
- 并发编程题目: 条件变量, 信号量
- 复习生产者消费者问题
printf字符串末尾没有换行:
- printf有libc的缓冲区
- setbuf(); fork的神坑(连缓冲区一起复制fork+printf两次, 6 or 8)
- 到文件:总是缓冲; 到中断: 换行
- ltrace有printf
- printf有libc的缓冲区
printf背后的系统调用: write
write写到哪: 文件描述符对应的文件, 例如一个设备/dev/ttyx, 或者是文件系统中的一个文件
文件系统如何实现 FAT, ext2(inode)
如何保护数据不受损坏:
- 把不可靠的磁盘变可靠: RAID; 奇偶校验允许一块盘坏; 校验位均匀分布在各个盘上
- 实现崩溃一致性: fsck, 日志